package com.leedsoft.service.entity;

import com.google.common.collect.Lists;
import com.leedsoft.common.Enums;
import com.leedsoft.common.SpringContextHolder;
import com.leedsoft.controller.vo.StepVo;
import com.leedsoft.controller.vo.TaskJsonVo;
import com.leedsoft.domain.*;
import com.leedsoft.mapper.AidBpmNodeMapper;
import com.leedsoft.mapper.AidStepMapper;
import com.leedsoft.mapper.AidTaskMapper;
import com.leedsoft.mapper.self.AidSelfMapper;
import com.leedsoft.service.AidService;
import org.apache.commons.lang3.StringUtils;

import java.util.Arrays;
import java.util.List;

/**
 * Created by leeds on 2017/6/20.
 */
public abstract class Step {
    protected Integer stepType;
    protected StepVo stepVo;
    protected Long planId;
    protected Long stepId;

    protected AidBpmNodeMapper nodeMapper = SpringContextHolder.getBean(AidBpmNodeMapper.class);
    protected AidStepMapper stepMapper = SpringContextHolder.getBean(AidStepMapper.class);
    protected AidSelfMapper aidSelfMapper = SpringContextHolder.getBean(AidSelfMapper.class);
    protected AidService aidService = SpringContextHolder.getBean(AidService.class);
    protected AidTaskMapper taskMapper = SpringContextHolder.getBean(AidTaskMapper.class);

    protected AidBpmNode coreNode;
    protected List<AidBpmSeqflow> flows = Lists.newArrayList();
    protected List<TaskJsonVo> expInfoTasks = Lists.newArrayList();

    public static Step getInstance(StepVo stepVo) {
        Integer type = stepVo.getType();
        Enums.StepType t = Enums.getEnum(Enums.StepType.class, type);
        if (t == null) throw new IllegalArgumentException("传入的环节类型不正确：" + type);
        Step res = null;
        try {
            res = t.getStepCls().newInstance();
            res.stepType = type;
            res.stepVo = stepVo;
            res.planId = stepVo.getPlanId();
        } catch (InstantiationException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        }
        return res;
    }
    public void build() {
        saveStep();
        genCoreNode();
        genViceNodes();
        genFlows();
        saveTasks();
    }

    protected abstract void wireCoreNode(AidBpmNode node);

    protected void genCoreNode() {
        AidBpmNode node = newNode();
        wireCoreNode(node);
        nodeMapper.insertSelective(node);
        coreNode = node;

        //设置Step no
        AidStep step = new AidStep();
        step.setId(stepId);
        step.setStep_no(coreNode.getCode());
        stepMapper.updateByPrimaryKeySelective(step);

        //设置指向核心节点的flow
        for (Integer lastCode : stepVo.getLastCodes()) {
            newFlow(lastCode, node.getCode());
        }

        //设置进入节点的has_to、to_switch
        updateToState(Arrays.asList(stepVo.getLastCodes()));
    }

    protected abstract void genViceNodes();

    /**
     * 生成所有除核心节点外的task节点。注意只有新建。不涉及指向已存在
     */
    protected void genNewTasks() {
        for (TaskJsonVo task : stepVo.getTaskJsonList()) {
            AidBpmNode node = newNode();
            node.setType(Enums.NodeType.TASK.getCode().shortValue());
            node.setAssignee(task.getAssignee());
            node.setBrief(task.getBrief());
            nodeMapper.insertSelective(node);

            task.setCode(node.getCode());
            task.setStep_id(stepId);

            AidBpmSeqflow flow = newFlow(coreNode.getCode(), node.getCode());
            if (stepType.equals(Enums.StepType.BRANCH.getCode())) {
                flow.setExp(task.getExp());
                flow.setLabel(task.getLabel());
            }
        }
    }

    private void genFlows() {
        aidSelfMapper.saveFlows(flows);
    }

    protected void saveTasks() {
        aidSelfMapper.saveTasks(stepVo.getTaskJsonList());
    }

    private void saveStep() {
        if (stepVo.getStepId() != null) {
            stepId = stepVo.getStepId();
            AidStep step = stepMapper.selectByPrimaryKey(stepId);
            if (step != null) {
                //更新操作，删除原有数据
                aidService.delStepWith(stepId);
            }
        } else {
            AidStep step = new AidStep();
            step.setPlan_id(planId);
            step.setType(stepType);
            step.setLast_codes(StringUtils.join(stepVo.getLastCodes(), ","));
            stepMapper.insertSelective(step);
            stepVo.setStepId(step.getId());
            stepId = step.getId();
        }
    }

    protected AidBpmNode newNode() {
        AidBpmNode node = new AidBpmNode();
        node.setPlan_id(planId);
        node.setCode(getMaxCode() + 1);
        node.setStep_id(stepId);
        return node;
    }

    protected AidBpmSeqflow newFlow(Integer from, Integer to) {
        AidBpmSeqflow flow = new AidBpmSeqflow();
        flow.setPlan_id(planId);
        flow.setFrom(from);
        flow.setTo(to);
        flow.setStep_id(stepId);
        flows.add(flow);
        return flow;
    }

    protected int getMaxCode() {
        Integer maxCode = aidSelfMapper.getMaxCode(planId);
        return maxCode == null ? 0 : maxCode;
    }

    public void updateToState(List<Integer> taskCodes) {
        AidTaskExample taskExample = new AidTaskExample();
        taskExample.createCriteria().andPlan_idEqualTo(planId).andCodeIn(taskCodes);
        AidTask task = new AidTask();
        task.setHas_to((short)1);
        if (stepType.equals(Enums.StepType.BRANCH.getCode())) task.setTo_switch((short)1);
        taskMapper.updateByExampleSelective(task, taskExample);
    }
}
